﻿using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WomanMotion.WebApi.Infrastructure.DataBaseCommon;
using WomanMotion.WebApi.Infrastructure.Ioc;

namespace WomanMotion.WebApi.Repository.IRepository
{
    /// <summary>
    /// 数据库仓储基本接口
    /// </summary>
    public interface IBaseRepository<TEntity> : ITransientDependency where TEntity : class
    {
        /// <summary>
        /// 数据库上下文
        /// </summary>
        /// <returns></returns>
        ISqlSugarClient GetDB();

        #region 添加

        /// <summary>
        /// 插入一个实体(异步)
        /// </summary>
        /// <param name="entity">实体对象</param>
        /// <returns></returns>
        Task<TEntity> InsertAsync(TEntity entity);

        /// <summary>
        /// 批量插入数据(异步)
        /// </summary>
        /// <param name="entity">数据集合</param>
        /// <returns>返回数据行数</returns>
        Task<int> InsertAsync(List<TEntity> entity);

        #endregion 添加

        #region 删除

        /// <summary>
        /// 删除一个实体(异步)
        /// </summary>
        /// <param name="id">ID主键</param>
        /// <returns>影响行数</returns>
        Task<int> DeleteAsync(object id);

        /// <summary>
        /// 批量删除数据(异步)
        /// </summary>
        /// <param name="ids">主键集合</param>
        /// <returns>影响行数</returns>
        Task<int> DeleteAsync(object[] ids);

        /// <summary>
        /// 根据条件删除数据(异步)
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        Task<int> DeleteAsync(Expression<Func<TEntity, bool>> expression);

        #endregion 删除

        #region 更新

        /// <summary>
        /// 更新数据(异步)
        /// </summary>
        /// <param name="entity">需要更新的实体</param>
        /// <returns>影响行数</returns>
        Task<int> UpdateAsync(TEntity entity);

        /// <summary>
        /// 批量更新数据(异步)
        /// </summary>
        /// <param name="entity">实体集合</param>
        /// <returns>影响行数</returns>
        Task<int> UpdateAsync(List<TEntity> entity);

        #endregion 更新

        #region 查询

        /// <summary>
        /// 查询单个数据(异步)
        /// </summary>
        /// <param name="expression">条件</param>
        /// <returns></returns>
        Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> expression);

        /// <summary>
        /// 查询单个带导航数据(异步)
        /// </summary>
        /// <param name="expression">条件</param>
        /// <param name="ignoreProperyNameList">需要忽略的导航属性</param>
        /// <returns></returns>
        Task<TEntity> GetNavAsync(Expression<Func<TEntity, bool>> expression, params string[] ignoreProperyNameList);

        /// <summary>
        /// 查询单个数据(同步)
        /// </summary>
        /// <param name="expression">条件</param>
        /// <returns></returns>
        TEntity Get(Expression<Func<TEntity, bool>> expression);

        /// <summary>
        /// 查询单个带导航数据(同步)
        /// </summary>
        /// <param name="expression">条件</param>
        /// <param name="ignoreProperyNameList">需要忽略的导航属性</param>
        /// <returns></returns>
        TEntity GetNav(Expression<Func<TEntity, bool>> expression, params string[] ignoreProperyNameList);

        /// <summary>
        /// 根据主键查询单个数据(异步)
        /// </summary>
        /// <param name="id">id主键</param>
        /// <returns></returns>
        Task<TEntity> GetByIDAsync(object id);

        /// <summary>
        ///根据主键查询单个带导航数据(异步)
        /// </summary>
        /// <param name="id">id主键</param>
        /// <param name="ignoreProperyNameList">需要忽略的导航属性</param>
        /// <returns></returns>
        Task<TEntity> GetByIDNavAsync(object id, params string[] ignoreProperyNameList);

        /// <summary>
        /// 根据主键查询单个数据(同步)
        /// </summary>
        /// <param name="id">id主键</param>
        /// <returns></returns>
        TEntity GetByID(object id);

        /// <summary>
        /// 根据主键查询单个带导航数据(同步)
        /// </summary>
        /// <param name="id">id主键</param>
        /// <param name="ignoreProperyNameList">需要忽略的导航属性</param>
        /// <returns></returns>
        TEntity GetByIDNav(object id, params string[] ignoreProperyNameList);

        /// <summary>
        /// 返回所有数据集合(异步)
        /// </summary>
        /// <returns></returns>
        Task<List<TEntity>> GetListAsync();

        /// <summary>
        /// 返回所有带排序数据集合(异步)
        /// </summary>
        /// <param name="orderby">排序数组字符串</param>
        /// <returns></returns>
        Task<List<TEntity>> GetListOrderByAsync(string[] orderby);

        /// <summary>
        /// 返回所有带导航数据集合(异步)
        /// </summary>
        /// <param name="ignoreProperyNameList">需要忽略的导航属性</param>
        /// <returns></returns>
        Task<List<TEntity>> GetListNavAsync(params string[] ignoreProperyNameList);

        /// <summary>
        ///返回所有带导航带排序数据集合(异步)
        /// </summary>
        /// <param name="orderby">排序数组字符串</param>
        /// <param name="ignoreProperyNameList">需要忽略的导航属性</param>
        /// <returns></returns>
        Task<List<TEntity>> GetListNavOrderByAsync(string[] orderby, params string[] ignoreProperyNameList);

        /// <summary>
        /// 按条件返回数据集合(异步)
        /// </summary>
        /// <param name="expression">条件</param>
        /// <returns></returns>
        Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> expression);

        /// <summary>
        /// 按条件返回带排序数据集合(异步)
        /// </summary>
        /// <param name="expression">条件</param>
        /// <param name="orderby">排序数组字符串</param>
        /// <returns></returns>

        Task<List<TEntity>> GetListOrderByAsync(Expression<Func<TEntity, bool>> expression, string[] orderby);

        /// <summary>
        /// 按条件返回带导航数据集合(异步)
        /// </summary>
        /// <param name="expression">条件</param>
        /// <param name="ignoreProperyNameList">需要忽略的导航属性</param>
        /// <returns></returns>
        Task<List<TEntity>> GetListNavAsync(Expression<Func<TEntity, bool>> expression, params string[] ignoreProperyNameList);

        /// <summary>
        ///按条件返回带排序带导航数据集合(异步)
        /// </summary>
        /// <param name="expression">条件</param>
        /// <param name="orderby">排序数组字符串</param>
        /// <param name="ignoreProperyNameList">需要忽略的导航属性</param>
        /// <returns></returns>

        Task<List<TEntity>> GetListNavOrderByAsync(Expression<Func<TEntity, bool>> expression, string[] orderby, params string[] ignoreProperyNameList);

        /// <summary>
        /// 查询是否有符合记录的数据存在(异步)
        /// </summary>
        /// <param name="expression">表达式</param>
        /// <returns>存在true,不存在false</returns>
        Task<bool> GetAnyAsync(Expression<Func<TEntity, bool>> expression);

        /// <summary>
        /// 查询存在数据的行数(异步)
        /// </summary>
        /// <param name="expression">表达式</param>
        /// <returns>数据行数</returns>
        Task<int> GetCountAsync(Expression<Func<TEntity, bool>> expression);

        /// <summary>
        /// 分页获取实体数据的KeyValuePair(异步)
        /// </summary>
        /// <param name="pars">分页查询对象</param>
        /// <returns>key是数据总数,value是数据集合</returns>
        Task<KeyValuePair<int, List<TEntity>>> GetPageKeyValuePairListAsync(QueryParameterBase pars);

        /// <summary>
        /// 分页获取包含导航实体数据的KeyValuePair(异步)
        /// </summary>
        /// <param name="pars">分页查询对象</param>
        /// <param name="ignoreProperyNameList">需要忽略的导航属性</param>
        /// <returns>key是数据总数,value是数据集合</returns>
        Task<KeyValuePair<int, List<TEntity>>> GetPageNavKeyValuePairListAsync(QueryParameterBase pars, params string[] ignoreProperyNameList);

        /// <summary>
        /// 分页查询单表数据(异步)
        /// </summary>
        /// <param name="pars">查询参数</param>
        /// <returns>通用返回结果</returns>
        Task<PageViewBase<List<TEntity>>> GetPageListAsync(QueryParameterBase pars);

        /// <summary>
        /// 分页查询单表带导航数据(异步)
        /// </summary>
        /// <param name="pars">查询参数</param>
        /// <param name="ignoreProperyNameList">需要忽略的导航属性</param>
        /// <returns>通用返回结果</returns>
        Task<PageViewBase<List<TEntity>>> GetPageNavListAsync(QueryParameterBase pars, params string[] ignoreProperyNameList);

        /// <summary>
        /// 多表连接分页查询(异步)
        /// 用法  CommonPage(db.Queryable<JoinTable1,JoinTable2>(...).Select(it=new class(){..}).MergeTable(),pars,orderbys,pageIndex,pagesize)
        /// </summary>
        /// <returns></returns>
        Task<PageViewBase<List<ViewModel>>> GetCommonPageListAsync<ViewModel>(ISugarQueryable<ViewModel> query, QueryParameterBase pars);

        /// <summary>
        /// 查询多表连接单条数据(异步)
        /// </summary>
        /// <typeparam name="ViewModel">表连接字段</typeparam>
        /// <param name="query">查询条件</param>
        /// <returns>多表连接VM</returns>
        Task<ViewModel> GetCommonFirstAsync<ViewModel>(ISugarQueryable<ViewModel> query);

        /// <summary>
        /// 查询多表连接单条数据(同步)
        /// </summary>
        /// <typeparam name="ViewModel"><表连接字段/typeparam>
        /// <param name="query">查询条件</param>
        /// <returns>多表连接VM</returns>
        ViewModel GetCommonFirst<ViewModel>(ISugarQueryable<ViewModel> query);

        /// <summary>
        /// 查询多表连接数据集合(异步)
        /// </summary>
        /// <typeparam name="ViewModel">表连接字段</typeparam>
        /// <param name="query">查询条件</param>
        /// <returns>多表连接VM</returns>
        Task<List<ViewModel>> GetCommonListAsync<ViewModel>(ISugarQueryable<ViewModel> query);

        #endregion 查询
    }
}